package pacBioSimple;

import tools.kmer.KmerSet_binary;
import tools.sequences.sequenceUtils;

public class PacBioSeedBridgingReduceExtend extends PacBioSeedBridgingKmer{

	protected StringBuilder tempKmer = null;
	
	public PacBioSeedBridgingReduceExtend(int seed1Pos, int distance,
			CodingTable table, KmerSet_binary ks, boolean dir, int repVal,
			KKmerList kmerVector, StringBuilder readSeq, Path candidatePath) {
		super(seed1Pos, distance, table, ks, dir, repVal, kmerVector, readSeq,
				candidatePath);
	}
	public PacBioSeedBridgingReduceExtend(int seed1Pos, int seed2Pos,int distance,
			CodingTable table, KmerSet_binary ks, boolean dir, int repVal,
			KKmerList kmerVector, StringBuilder readSeq, Path candidatePath)
	{
		super(seed1Pos, seed2Pos, distance, table, ks, dir, repVal, kmerVector, readSeq, candidatePath);
	}
	
	public PacBioSeedBridgingReduceExtend(StringBuilder seed_1, StringBuilder seed_2, int seed1Pos, int seed2Pos, int distance, CodingTable table, KmerSet_binary ks, boolean dir, int repVal, KKmerList kmerVector, StringBuilder readSeq, Path candidatePath)
	{
		super(new StringBuilder(seed_1.substring(seed_1.length()-ks.getKmerSize(), seed_1.length())), seed_2, seed1Pos, seed2Pos, distance, table, ks, dir, repVal, kmerVector, readSeq, candidatePath);
		tempKmer = new StringBuilder(seed_1.substring(0, seed_1.length()-ks.getKmerSize()));
	}
	
	
	  
	public void run()
	{
		MyUtil.logging("seed1: " + this.seed1+ " seed2: "+ this.seed2 + " ausgabe");
		//System.out.println("seed1: " + this.seed1+ " seed2: "+ this.seed2);

		id=0;
		//here we have to fill all the nasty things building up the stack, saving the result
		//first add the first root node
		if(stack.empty())
		{
			stack.push(0);
			++id;
		}
		int distance_reaced=0;
		StringBuilder kmer=new StringBuilder(this.seed1);	
		while(!stack.empty())
		{		
//			++counter;
//			log.log(Level.WARNING,"StackDeep: "+stack.getLength() + "StackNode: "+stack.peek().getId()+" "+stack.peek().getStatus() +" Distance "+ distance+"\n");
			//if(counter % 100==0)
			MyUtil.logging("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
			MyUtil.logging("kmer "+kmer);
			//System.out.println("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
			//System.out.println("kmer "+kmer);
			if(stack.peek()>=4)
			{
				//System.out.println("peek erreicht");
				kmer=pop(kmer,false);
			}
			else if(stack.getLength() >= this.distance)
			{
				MyUtil.logging("Distance reached");
				//System.out.println("Distance reached");
				if(seed2!=null)
				{
					kmer=pop(kmer,false);
				}
				else
				{
					kmer=pop(kmer,true);
				}
				++distance_reaced;
				if(distance_reaced>100)
				{
					break;//vorläufig.. alignment wäre besser falls man merkt das die sequence zu sehr divergiert cut und gehe weiter
				}
			}
			else if(seed2!=null && kmer.length()>ks.getKmerSize() && kmer.indexOf(seed2.toString())!=-1)
			{
				kmer=pop(kmer,true);
			}
			else
			{
				//check last element
				//building up the kmer
				StringBuilder tempNewKmer = new StringBuilder(kmer.substring(kmer.length()-ks.getKmerSize(), kmer.length()));
				tempNewKmer.append(codingTable.getCodingTableEntry(stack.peek()));
				if(kmer.indexOf(tempNewKmer.toString()) !=-1)
				{
					MyUtil.logging("double kmer" + tempNewKmer);
					//System.out.println("double kmer" + tempNewKmer);
					stack.setPeek(stack.peek()+1);
					setRepatPath(kmer);
				}
				else
				{					
					kmer.append(codingTable.getCodingTableEntry(stack.peek()));
					//if(counter % 100==0)
					MyUtil.logging("Path "+kmer.toString());
					//System.out.println("Path "+kmer.toString());
					//check Kmer
					//int a=kmer.length();
					//int b = ks.getKmerSize();
					//String test = kmer.substring(kmer.length()-ks.getKmerSize(), kmer.length());
					int kmerVal = checkKmerDistribution(kmer.substring(kmer.length()-ks.getKmerSize(), kmer.length()));
					MyUtil.logging(" kmer val "+ kmerVal);
					//System.out.println(" kmer val "+ kmerVal);
					//				if(kmerVal!=0)
	//				{
	//					System.out.println("Kmer "+kmer.substring(kmer.length()-ks.getKmerSize(), kmer.length())+" "+kmerVal);
	//					System.out.println("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
	//				}
					if(seed2!=null && kmer.length()>ks.getKmerSize() && kmer.indexOf(seed2.toString())!=-1) //catch the case that a seed is been called as rep kmer.. TODO NOT SURE I think now you have to go down instead increasing the string.. 
					{
						kmer = pop(kmer,true);
					}
					else if(kmerVal!=0 && kmerVal < repVal)
					{
						stack.push(0);
						++id;
					}					
					else if(kmerVal>repVal) //repeat kmers!  
					{
						MyUtil.logging("expanding kmer "+ kmerVal);
						MyUtil.logging("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
						MyUtil.logging("kmer "+kmer);
						MyUtil.logging(String.valueOf(kmerVector.getKmerSize()));
						MyUtil.logging("start");
//						System.out.println("expanding kmer "+ kmerVal);
//						System.out.println("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
//						System.out.println("kmer "+kmer);
//						System.out.println(kmerVector.getKmerSize());
//						System.out.println("start");
						//here i have to go back until I check every other case
						//first save kmer
						//15029
						setRepatPath(kmer); // save the current path but indicating it is a repeat!
						kmer.deleteCharAt(kmer.length()-1);
						tempNewKmer = new StringBuilder(kmer);
						stack.setPeek(stack.peek()+1);
						boolean found=false;
						while(stack.peek()!=4)
						{
							MyUtil.logging("kmer expand "+ kmerVal);
							MyUtil.logging("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
							//check all other possible solution
							tempNewKmer.append(codingTable.getCodingTableEntry(stack.peek()));
							kmerVal = checkKmerDistribution(tempNewKmer.substring(tempNewKmer.length()-ks.getKmerSize(), tempNewKmer.length()));
							if(kmerVal!=0 && kmerVal<repVal)
							{
								stack.push(0);
								++id;
								kmer=tempNewKmer;
								found=true;
								break;
							}
							else if(kmerVal>=repVal)
							{
								setRepatPath(tempNewKmer);
								MyUtil.logging("setrepeatpath "+ tempNewKmer);
							}
							tempNewKmer.deleteCharAt(tempNewKmer.length()-1);
							stack.setPeek(stack.peek()+1);	
						}
						if(!found)
						{
							//now we have to jump further up in the tree... I do not like that...but save runtime.
							int i =0;
							while(!stack.empty() && kmer.length()>ks.getKmerSize() && i<5)
							{
								stack.pop();
								kmer.deleteCharAt(kmer.length()-1);
								++i;
								MyUtil.logging("StackDeep decresing: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
								MyUtil.logging("kmer decresing "+kmer);
//								System.out.println("StackDeep decresing: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
//								System.out.println("kmer decresing "+kmer);
							}
							stack.setPeek(stack.peek()+1);
						}
						MyUtil.logging("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
						MyUtil.logging("kmer "+kmer);
//						System.out.println("StackDeep: "+stack.getLength() + " " +stack.peek() +" Distance "+ distance +"\n");
//						System.out.println("kmer "+kmer);
					}
					else
					{
						kmer.deleteCharAt(kmer.length()-1);
						stack.setPeek(stack.peek()+1);
					}
				}
			}
		}
		System.out.println("finish now save the data accordenly ");
		if(this.candidate.size()==0)
		{
			this.candidate.add(new StringBuilder(""));
		}
		
//		if(tempKmer !=null)
//		{
//			System.out.println(tempKmer);
//		}
		
		if(tempKmer!=null)
		{
			for(int i=0; i < this.candidate.size();++i)
			{
				StringBuilder temp=null;
				if(dir)
				{
					temp=sequenceUtils.reverseComplement2(tempKmer);
				}
				else
					temp=tempKmer;
				
				temp.append(this.candidate.get(i));
				this.candidate.set(i,new StringBuilder(temp));
			}
			
			for(int i=0; i < this.repeatsStoppPath.size();++i)
			{
				StringBuilder temp=null;
				if(dir)
				{
					temp=sequenceUtils.reverseComplement2(tempKmer);
				}
				else
					temp=tempKmer;
				
				temp.append(this.repeatsStoppPath.get(i));
				this.repeatsStoppPath.set(i,new StringBuilder(temp));
			}
		}
		setPaths();
	}



}
